package barrel_kong;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import modalities.ObservableThing;
import music.MP3;
import music.PlayList;
import kong_gui_items.Banana;
import kong_gui_items.Barrel;
import kong_gui_items.BarrelFinal;
import kong_gui_items.BaseGraphics;
import kong_gui_items.Coin;
import kong_gui_items.CurrentBarrel;
import kong_gui_items.DialogScreen;
import kong_gui_items.DirectionalArrowLeft;
import kong_gui_items.DirectionalArrowUp;
import kong_gui_items.Display;
import kong_gui_items.DisplayBananaCount;
import kong_gui_items.FinishBackground;
import kong_gui_items.FinishPlatform;
import kong_gui_items.GameOverBackground;
import kong_gui_items.HudLife;
import kong_gui_items.InfoKeyDisplay;
import kong_gui_items.L_Rock;
import kong_gui_items.LevelBackground;
import kong_gui_items.ModalityHelperDisplay;
import kong_gui_items.Monkey;
import kong_gui_items.ScoreDisplay;
import kong_gui_items.TracingPoint;
import kong_gui_items.VoiceFrequencyWidget;
import kong_gui_items.Wide_Rock;

/** This is the Model*/
public class GameState {

	LevelBackground background;
	VoiceFrequencyWidget widget;
	HudLife hud;
	Display userDisplay;
	Barrel currentBarrel;
	Monkey donkeyKong;
	DisplayBananaCount bananaDisplay;
	DirectionalArrowLeft leftRight;
	DirectionalArrowUp upDown;
	LinkedList<BaseGraphics> levelItems;
	DialogScreen startDialog;
	GameOverBackground gameOverBackground;
	FinishBackground finishBackground;
	BarrelFinal finalBarrel;
	ModalityHelperDisplay actionsToDo;
	InfoKeyDisplay displayAvailableKeys;
	TracingPoint tpt;
	ScoreDisplay score;
	String levelsDescFile;
	int firstLevelToPlay;

	Coin uniqueCoin;
	MP3 [] soundList;
	List<Banana> bananasCollected  = new ArrayList<Banana>();

	public static Integer windowWidth = 800;
	public static Integer windowHeight = 680;
	public static Integer timeForQuestion = 7;
	public static Integer bananaCount =0;
	private String currentLevelName;
	

	int lifes = 6;
	double maxPowerShot = 130.00; //speed for cinematique equation
	Coin bigEndcoin;


	public Coin getBigEndcoin() {
		return bigEndcoin;
	}


	//Constructor
	public GameState(String levelsDescFile, int firstLevelToPlay){

		soundList = new MP3[12];
		//Load MP3 FIles
		soundList[PlayList.WelcomScreen_Music] = new MP3(".\\Resources\\Music\\Dave Wise - Theme.mp3", true);
		soundList[PlayList.Barrel_Shoot_Sound] = new MP3(".\\Resources\\Music\\Barrel_Shot.mp3");
		soundList[PlayList.Barrel_Reception_Sound] = new MP3(".\\Resources\\Music\\Boing.mp3");
		soundList[PlayList.final_Reception_Sound] = new MP3(".\\Resources\\Music\\Dave Wise - (SFX) bonus win.mp3");
		soundList[PlayList.Banana_Touched_Sound] = new MP3(".\\Resources\\Music\\PickupBanana.wav");
		soundList[PlayList.Coin_Touched_Sound] = new MP3(".\\Resources\\Music\\Electrical_Sweep-Sweeper-1760111493.mp3");
		soundList[PlayList.Live_Lost_Sound] = new MP3(".\\Resources\\Music\\Fail.wav");
		soundList[PlayList.Game_Over_Music] = new MP3(".\\Resources\\Music\\Donkey Kong Country 2 OST Game Over.mp3");
		soundList[PlayList.Banana_final_Burst_Sound] = new MP3(".\\Resources\\Music\\Barrel_Shot.mp3");
		soundList[PlayList.CoinRaise_Sound] = new MP3(".\\Resources\\Music\\Choir.mp3");
		soundList[PlayList.CountScreenMusic] = new MP3(".\\Resources\\Music\\Dave Wise - Bonus Room Blitz.mp3", true);

		this.levelsDescFile =  levelsDescFile;
		this.firstLevelToPlay = firstLevelToPlay;
		levelItems = new LinkedList<BaseGraphics>();

		reloadCurrentLevel();
	}


	public void loadLightComponentsForEnd(){

		for(BaseGraphics g : levelItems)
			g.setVisible(false);
		levelItems.clear();
		levelItems.addAll(addItemsForEndOfGame());
	//	levelItems.addAll(createGameBackground());
		assignateObjectToLocalExetrnalsRef();	

	}

	public void reloadCurrentLevel() {

		
		for(BaseGraphics g : levelItems)
			g.setVisible(false);
		levelItems.clear();

		levelItems.addAll(loadAndResetLevel(levelsDescFile, firstLevelToPlay));
		levelItems.addAll(createGameBackground());
		//levelItems.addAll(addItemsForEndOfGame());
		levelItems.add(new DialogScreen());
		bananaCount =0;
		getBananasCollected().clear();
		this.lifes = 6;
		assignateObjectToLocalExetrnalsRef();

		for(MP3 music : soundList)
		{
			music.close();
		}


		//soundList = new MP3[12];
		//Load MP3 FIles
		soundList[PlayList.WelcomScreen_Music] = new MP3(".\\Resources\\Music\\Dave Wise - Theme.mp3", true);
		soundList[PlayList.Barrel_Shoot_Sound] = new MP3(".\\Resources\\Music\\Barrel_Shot.mp3");
		soundList[PlayList.Barrel_Reception_Sound] = new MP3(".\\Resources\\Music\\Boing.mp3");
		soundList[PlayList.final_Reception_Sound] = new MP3(".\\Resources\\Music\\Dave Wise - (SFX) bonus win.mp3");
		soundList[PlayList.Banana_Touched_Sound] = new MP3(".\\Resources\\Music\\PickupBanana.wav");
		soundList[PlayList.Coin_Touched_Sound] = new MP3(".\\Resources\\Music\\Electrical_Sweep-Sweeper-1760111493.mp3");
		soundList[PlayList.Live_Lost_Sound] = new MP3(".\\Resources\\Music\\Fail.wav");
		soundList[PlayList.Game_Over_Music] = new MP3(".\\Resources\\Music\\Donkey Kong Country 2 OST Game Over.mp3");
		soundList[PlayList.Banana_final_Burst_Sound] = new MP3(".\\Resources\\Music\\Barrel_Shot.mp3");
		soundList[PlayList.CoinRaise_Sound] = new MP3(".\\Resources\\Music\\Choir.mp3");
		soundList[PlayList.CountScreenMusic] = new MP3(".\\Resources\\Music\\Dave Wise - Bonus Room Blitz.mp3", true);


	}



	private LinkedList<BaseGraphics> createGameBackground() {

		LinkedList<BaseGraphics> gameItems = new LinkedList<BaseGraphics>();
		gameItems.clear();
		gameItems.add(new VoiceFrequencyWidget(700, 480));
		gameItems.add(new Display());
		gameItems.add(new DirectionalArrowLeft());
		gameItems.add(new DirectionalArrowUp());
		gameItems.add(new DisplayBananaCount());
		gameItems.add(new HudLife());
		gameItems.add(new ModalityHelperDisplay(680, 400));
		gameItems.add(new GameOverBackground());
		gameItems.add(new TracingPoint());
		return gameItems;

	}

	private LinkedList<BaseGraphics> addItemsForEndOfGame() {

		LinkedList<BaseGraphics> gameItems = new LinkedList<BaseGraphics>();
		gameItems.add(new FinishBackground());		
		gameItems.add(new ScoreDisplay());
		gameItems.add(new ModalityHelperDisplay(680, 400));
		gameItems.add(new Display());
		gameItems.add(new DirectionalArrowLeft());
		gameItems.add(new DirectionalArrowUp());
		gameItems.add(new DisplayBananaCount());
		gameItems.add(new HudLife());
		
		Coin tmp = new Coin(100,200,true);
		tmp.setVisible(false);
		gameItems.add(tmp);		
		
		//XY position is set in the Monkey.enterbarrel function.
		gameItems.add(new Monkey(0,0, ".\\Resources\\Picts\\donkey_smil_big.png"));
		gameItems.add(new CurrentBarrel());
		gameItems.add(new InfoKeyDisplay(60, 100));
		
		
		return gameItems;
	}

	private LinkedList<BaseGraphics> loadAndResetLevel(String levelDef, int currentLevel) {

		LinkedList<BaseGraphics> gameItems = new LinkedList<BaseGraphics>();

		try {
			
			
			LevelLoader ll = new LevelLoader(levelDef, currentLevel);
			currentLevelName = ll.getLevelName();
			gameItems.addAll(ll.getGameItems());
			soundList[PlayList.Level_Music] = ll.getLevelMusic();

		} catch (IOException e) { e.printStackTrace(); }


		return gameItems;
	}

	private void assignateObjectToLocalExetrnalsRef(){

		donkeyKong = null;
		currentBarrel = null;
		background = null;
		widget = null;
		userDisplay = null;
		hud = null;
		leftRight = null;
		upDown = null;
		startDialog = null;
		finishBackground  = null;
		finalBarrel  = null;
		gameOverBackground  = null;
		bananaDisplay  = null;
		uniqueCoin  = null;
		actionsToDo  = null;
		tpt  = null;
		score  = null;
		displayAvailableKeys = null;
		bigEndcoin = null;

		//Get references on interactible unique objects as the monkey, etc
		for(BaseGraphics item : levelItems)
		{
			if(item instanceof Monkey) { donkeyKong = (Monkey) item; }
			if(item instanceof CurrentBarrel) { currentBarrel = (Barrel) item;}
			if(item instanceof LevelBackground) { background = (LevelBackground) item;}
			if(item instanceof VoiceFrequencyWidget) {widget = (VoiceFrequencyWidget) item;}
			if(item instanceof Display){userDisplay = (Display) item;}
			if(item instanceof HudLife){hud = (HudLife)item;}
			if(item instanceof DirectionalArrowLeft){leftRight = (DirectionalArrowLeft) item;}
			if(item instanceof DirectionalArrowUp){upDown = (DirectionalArrowUp) item;}
			if(item instanceof DialogScreen){startDialog = (DialogScreen) item;}
			if(item instanceof FinishBackground){finishBackground = (FinishBackground) item;}
			if(item instanceof BarrelFinal){finalBarrel = (BarrelFinal) item;}
			if(item instanceof GameOverBackground){gameOverBackground = (GameOverBackground) item;}
			if(item instanceof DisplayBananaCount){bananaDisplay = (DisplayBananaCount)item;}
			if(item instanceof Coin){uniqueCoin = (Coin) item;}
			if(item instanceof ModalityHelperDisplay) {actionsToDo = (ModalityHelperDisplay)item;}
			if(item instanceof TracingPoint){tpt = (TracingPoint)item;}
			if(item instanceof ScoreDisplay){score = (ScoreDisplay)item;}
			if(item instanceof Coin){bigEndcoin = (Coin)item;}
			if(item instanceof InfoKeyDisplay){displayAvailableKeys = (InfoKeyDisplay)item;}

		}
		
		if(startDialog != null){
			startDialog.setLevelName(currentLevelName);
		}
		if(currentBarrel!= null)
		{
			donkeyKong.enterBarrel(currentBarrel);	
			manageArrows();
		}
	}

	//Getters
	public double getBarrelAngle() 			{return currentBarrel.getAngle();}
	public double getVoicePower()			{return widget.getFrequencyLevel();}
	public Barrel getCurrentBarrel()		{return currentBarrel;}
	public int getLifes() 					{return lifes;}
	public Monkey getDonkeyKong() 			{return donkeyKong;}
	public Integer getWindowWidth() 		{return windowWidth;}
	public Integer getWindowHeight() 		{return windowHeight;}
	public double getmaxPowerShot() 		{return maxPowerShot;}
	public Display getUserDisplay() 		{return userDisplay;}
	public GameOverBackground getgameOverBackground()  	{return gameOverBackground;}
	public FinishBackground getfinishBackground() 		{return finishBackground;}
	public BarrelFinal getfinalBarrel() 				{return finalBarrel;}
	public DisplayBananaCount getBananaDisplay() { return bananaDisplay;}
	public List<Banana> getBananasCollected() {return bananasCollected;}
	public Integer getBananaCount() { return bananaCount; }
	public Coin getUniqueCoin() { return uniqueCoin;}
	public MP3[] getSoundList() { return soundList; }
	public ModalityHelperDisplay getActionsToDo() { return actionsToDo; }
	public VoiceFrequencyWidget getVoiceWidget() { return widget; }
	public TracingPoint getTracingPoint() {return tpt;}
	public HudLife getHud() {return hud;}
	public ScoreDisplay getScore() {return score; }
	public int getCurrentLevel() { return firstLevelToPlay; }

	public InfoKeyDisplay getDisplayAvailableKeys() { return displayAvailableKeys; }


	public void setDisplayAvailableKeys(InfoKeyDisplay displayAvailableKeys) {
		this.displayAvailableKeys = displayAvailableKeys;
	}

	public void setCurrentLevel(int currentLevel) {
		this.firstLevelToPlay = currentLevel;
	}


	public void setScore(ScoreDisplay score) {
		this.score = score;
	}


	public void setActionsToDo(ModalityHelperDisplay actionsToDo) {
		this.actionsToDo = actionsToDo;
	}


	public void setUniqueCoin(Coin uniqueCoin) {
		this.uniqueCoin = uniqueCoin;
	}


	public  void addBananasToCount(List<Banana> bananasCollected) {
		GameState.bananaCount = bananaCount + bananasCollected.size();
		this.bananasCollected.addAll(bananasCollected);
		bananasCollected.clear();
		bananaDisplay.setNbBanana(bananaCount);
	}


	public void setBananasCollected(List<Banana> bananasCollected) {
		this.bananasCollected = bananasCollected;
		this.bananaDisplay.setNbBanana(bananasCollected.size());
	}



	public void setBananaDisplay(DisplayBananaCount bananaDisplay) {
		this.bananaDisplay = bananaDisplay;
	}

	//Setters

	public LinkedList<BaseGraphics> getLevelItems() 
	{
		return levelItems;
	}
	public void setLifes(int lifes){
		this.lifes = lifes;
		this.hud.setLifeRemaining(lifes);
	}
	public void setBarrelAngle(Double angle){
		currentBarrel.setAngle(angle);
		userDisplay.setAngle(angle);
	}


	public void setBarrelPosition(Integer position)
	{
		//Detection of collision with rocks
		currentBarrel.setPosition(position, levelItems);
		userDisplay.setBarrelPosX(currentBarrel.getX());
		userDisplay.setBarrelPosY(currentBarrel.getY());
		manageArrows();

	}
	public void setgameOverBackground(GameOverBackground gameOverBackground) 		{this.gameOverBackground = gameOverBackground;}
	public void setfinalBarrel(BarrelFinal finalBarrel) 				{this.finalBarrel = finalBarrel;}
	public void setfinishBackground(FinishBackground finishBackground)			{this.finishBackground = finishBackground;}

	public void manageArrows(){

		
		//Manage the arrow to show availible directions
		if(currentBarrel.isVertical())
		{
			leftRight.setVisible(false);
			upDown.setVisible(true);
			upDown.setX(currentBarrel.getX()+2);
			upDown.setY(currentBarrel.getY()-43);
		}
		else if(!currentBarrel.isVertical())
		{
			leftRight.setVisible(true);
			upDown.setVisible(false);
			leftRight.setX(currentBarrel.getX()-43);
			leftRight.setY(currentBarrel.getY());
		}
	}


	public void MakeArrowsBlink(){

		leftRight.setVisible(false);
		upDown.setVisible(false);
		
		//Manage the arrow to show availible directions
		if(currentBarrel.isVertical() &&  currentBarrel.getArrowsShown())
		{
			leftRight.setVisible(false);
			upDown.setVisible(true);
			upDown.setX(currentBarrel.getX()+2);
			upDown.setY(currentBarrel.getY()-43);
		}
		else if(!currentBarrel.isVertical() &&  currentBarrel.getArrowsShown())
		{
			leftRight.setVisible(true);
			upDown.setVisible(false);
			leftRight.setX(currentBarrel.getX()-43);
			leftRight.setY(currentBarrel.getY());
		}
	}
 
	public void showStartDialog(boolean show){
		startDialog.setVisible(show);
	}

	public void setVoicePower(Double voicePower)
	{
		widget.setFrequencyLevel(voicePower);
		userDisplay.setPower(voicePower);

	}
	public int useLife()
	{
		return hud.useLife();
	}
	public void setCurrentBarrel(Barrel item)
	{
		this.currentBarrel = item;
	}

	public void replayLevel() {
		reloadCurrentLevel();		
	}

	public void nextLevel() {
		firstLevelToPlay++;
		reloadCurrentLevel();		
	}
}